﻿#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>

//<1>sqrt库函数
//int main()
//{
//	double i = sqrt(16);
//	printf("%lf\n", i);
//
//	return 0;
//}



//<2>写⼀个加法函数，完成2个整型变量的加法操作。
//int Add(int x, int y)//用x代表a，用y代表b
//{
//	int z = x + y;
//	return z;//z是整型，所以Add函数返回类型是整型，Add前面应该加上int
//}
//
//int main()
//{
//	int a = 0;
//	int b = 0;
//	scanf("%d %d", &a, &b);
//	int c = Add(a, b);//int c就是Add函数的返回值，a和b就是Add函数的传递的参数
//						//函数Add相加的结果要用一个变量表示出来
//	printf("%d\n", c);
//
//	return 0;
//}



//<3>不需要传参，也不需要返回类型的函数（自定义函数）
//void Print(void)//第一个void表示不需要返回值，第二个void表示不需要传参去计算什么
//{
//	printf("YES");
//}
//
//int main()
//{
//	Print();//调用Print函数
//	return 0;
//}



//<4>实现一个函数，求两个整数的较大值
//int get_max(int x, int y)//函数定义中，括号中的参数就是形参，因只有真正调用这个函数时，形参才会申请空间，不用这个函数时，只是一个形式，不占内存空间
//{
//	return (x > y ? x : y);//写括号时，三目操作符的；要写在括号外面
//}
//int main()
//{
//	int a = 0;
//	int b = 0;
//	scanf("%d %d", &a, &b);
//	int c = get_max(a, b);//调用函数时，传递给函数的参数就是实参
//							//比较两个整数的较大值，要传参到比较函数中进行比较，而比较函数又要给出结果，所以又要返回值，要有返回类型
//	printf("%d\n", c);
//
//	return 0;
//}			//注：形参是实参的一份临时拷贝，形参的名字可以与实参名不一样



//<5>输入一个数，运用自定义函数，如果是奇数，就返回1，如果是偶数就返回0
//int is_odd(int a)
//{
//	if (a % 2 == 1)
//	{
//		return 1;//return执行后，语句彻底返回，不再执行后边的代码（执行性非常强）
//	}
//	else
//	{
//		return 0;//return后面可以跟一个数值
//	}
//}

//int is_odd(int a)
//{
//	return (a % 2);//return后面也可以跟一个表达式
//}

//int main()
//{
//	int a = 0;
//	scanf("%d", &a);
//	int b = is_odd(a);
//	if (b == 1)
//	{
//		printf("%d是奇数", a);
//	}
//	else
//	{
//		printf("%d是偶数", a);
//	}
//	return 0;
//}

//<6>输入一个数n，如果是正数，则打印1~n的数
//void test(int a)
//{
//	if (a >= 0)
//	{
//		int i = 0;
//		for (i = 0; i <= a; i++)
//		{
//			printf("%d ", i);
//		}
//	}
//	else
//	{
//		printf("负数不具备打印条件");
//	}
//	return;//这边我用调用函数中的打印完成了题目要求，就不需要返回值到主函数中继续操作，return返回值就没有什么意义了，所以后边可以不加值
//}		   //甚至我这边可以不用return；

//int main()
//{
//	int a = 0;
//	scanf("%d", &a);
//	test(a);
//
//	return 0;
//}

//int test()
//{
//	int n = 0;
//	scanf("%d", &n);//8
//	if (n<4)
//		return 3.5;//return返回的值和函数返回类型不⼀致，系统会⾃动将返回的值隐式转换为函数的返回类型。
//				   //这边3.5就不是int整型的返回类型，这时候会隐性转换为int类型，如果返回成功，打印结果为3，后面的0.5去掉了
//				   
//					//如果函数中存在if等分⽀的语句，则要保证每种情况下都有return返回，否则会出现编译错误。
//				   //这边n>=4就没有return返回，就容易出现编译错误
//}
//int main()
//{
//	int r = test();//3
//	printf("%d\n", r);
//	return 0;
//}



//<7>写⼀个函数对将⼀个整型数组的内容，全部置为-1，再写⼀个函数打印数组的内容。（一维数组）
//void set_arr(int arr[], int sf)//void表示不需要返回值到主函数中，因为主函数中没有设置与set_arr处理的值相关的计算或打印
//{
//	int i = 0;//设置下标变量，以便访问元素
//	for (i = 0; i <= sf-1; i++)
//	{
//		arr[i] = -1;//循环把数组元素全部变成-1
//	}
//
//}
//void Print_arr(int arr[], int sf)//传递的参数数组arr如果要访问元素，必须要有[]，不然不能设置下标并访问元素
//								//但是一般都需要加[]，因为传参数组就是为了对数组中的元素进行操作
//							//[]内部的数组长度可以不用写
//{
//	int i = 0;
//	for (i = 0; i <= sf-1; i++)
//	{
//		printf("%d ", arr[i]);//循环打印出数组中的每个元素
//	}
//
//}
//
//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//给出一个数组
//	int sf = sizeof(arr) / sizeof(arr[0]);//设置数组元素个数，以便能循环中访问每个下标从而访问每个元素
//	set_arr(arr,sf);//自定义函数设置为1，传参数组只需要写数组名
//	
//	Print_arr(arr, sf);
//
//	return 0;
//}

//写⼀个函数将⼀个整型数组的内容，全部置为-1，再写⼀个函数打印数组的内容。（二维数组）
//void set_arr(int arr[][5])//形参要加类型在后面
//{
//	int j = 0;//通过行和列的两个变量和两个循环来实现个数上的计算，从而访问数组中所有元素
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		for (j = 0; j < 5; j++)
//		{
//			arr[i][j] = -1;
//		}
//	}
//}
//void Print_arr(int arr[][5])//二维数组形参的列可以省略
//{
//	int i = 0;
//	int j = 0;
//	for (i = 0; i < 3; i++)
//	{
//		for (j = 0; j < 5; j++)
//		{
//			printf("%d ", arr[i][j]);
//		}
//		printf("\n");
//	}
//
//}
//int main()
//{
//	int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6,},{3,4,5,6,7} };
//	set_arr(arr,3,5);
//
//	Print_arr(arr,3,5);
//
//	return 0;
//}



//<8>计算某年某⽉有多少天（用函数的嵌套调用实现）
//int is_leap_year(int(y))
//{
//	if ((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0))
//		return 1;
//	else
//		return 0;
//}
//int get_days_of_month(int y, int m)
//{
//	int days[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
//			//下标 0  1  2  3  4  5  6  7  8  9  10  11
//	int day = days[m - 1];
//	int is_leap_year(y);//再调用函数中再调用函数，就是函数的嵌套调用
//						//这里的返回值用int来表示就行
//	if (is_leap_year(y)&&(m == 2))//这里的返回值用整个函数名以及传递的参数来表示
//		day += 1;
//	return day;
//
//}
//int main()
//{
//	printf("请输入年份，月份：");
//	int year = 0;
//	int month = 0;
//	scanf("%d %d", &year, &month);
//	int day = get_days_of_month(year, month);//这里的返回值要用int day = 来实现，并且int day = 已经在这里实现了初始化，不需要再上面进行定义
//	
//	printf("%d\n", day);
//
//	return 0;
//}



//<9>函数的链式访问
//int main()
//{
//	//计算一个字符串的长度
//	int len = strlen("acbdef");
//	printf("%d ", len);
//
//	return 0;
//}

//int main()
//{
//	//计算一个字符串的长度
//	printf("%d ", strlen("acbdef"));//strlen的返回值就是计算的字符串长度
//									//上面运用变量来表示strlen的返回值，并把变量放入printf中进行打印
//									//但是太麻烦了，这边直接把strlen函数放入printf函数中进行打印
//									//把函数的返回值作为另一个函数的参数，就是链式访问
//	return 0;
//}

//int main()
//{
//	printf("%d\n", printf("%d", printf("%d",43)));//打印4321
//	//注：函数的返回值由函数本身的语法决定，比如printf函数的返回值就是所打印字符的个数，而不是打印的字符，跟打印的功能不一样
//	//    而strlen的返回值跟它的功能是一样的，就是字符串的长度
//	//	  函数的返回值可能跟函数本身的功能一样，也可能不一样
//	printf("%d\n", printf("%d ", printf("%d ",43)));//打印43 3 2，printf函数的返回值是打印字符的个数，空格也是字符
//
//
//	return 0;
//}



//<10>函数的定义和声明（单个文件）
////判断⼀年是不是闰年
//int is_leap_year(int y);//函数的声明，如果函数的定义放在函数调用的后面，就要进行函数的声明
//
//int main()
//{
//	int y = 0;
//	scanf("%d", &y);
//	int r = is_leap_year(y);//函数的调用
//	if (r == 1)
//		printf("闰年\n");
//	else
//		printf("⾮闰年\n");
//	return 0;
//}
//
//int is_leap_year(int y)//函数的定义
//{
//	if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
//		return 1;
//	else
//		return 0;
//}



//<11>函数的定义和声明（多个文件）
//判断⼀年是不是闰年

//自定义
//#include "add.h"//函数的声明（用头文件）
//
//#pragma comment(lib,"调试草稿.lib")//对静态库文件（加密的源文件）的引用
//
//
////主函数的功能
//int main()
//{
//	int y = 0;
//	scanf("%d", &y);
//	int r = is_leap_year(y);//函数的调用（用主源文件）
//	if (r == 1)
//		printf("闰年\n");
//	else
//		printf("⾮闰年\n");
//	return 0;
//}
////函数的定义（在add.c文件中，用副源文件）
////分为多个文件的意义是在写大项目时，可以分工协作
////另一个意义是可以挑出源文件进行加密，先挑出源文件，新建一个项目，把源文件复制到最小项目文件中，并在项目中打开源文件，在属性中进行配置类型的转换
////转换成静态库类型，在把转换的lib（静态库文件，在Debug文件中）复制到原有最小项目文件中，并在项目中引用加密源文件（加密源文件也可以打开，但是看不到内容），就可以完成对特殊源文件的加密
//



//<12>extern声明外部源文件的符号
// int a = 0;//放在外部源文件中
//extern int a;//声明外部源文件，而非头文件
//void test()
//{
//	printf("2:	%d\n", a);
//}
//int main()
//{
//	printf("1:	%d\n", a);
//	test();
//	printf("3:	%d\n", a);
//
//	return 0;
//}



//<13>static修饰局部变量
//void test()
//{
//	int a = 2;
//	a++;
//	printf("%d\n", a);
//}//a每次出大括号表示生命周期结束；再次进入下一次循环时，重新创建变量
//int main()
//{
//	int i = 0;
//	for (i = 0; i < 5; i++)//表示循环5次
//	{
//		test();
//	}
//
//	return 0;
//}

//void test()
//{
//	static int a = 2;//用ststic修饰局部变量时，局部变量作用域不变，但生命周期变长（本质上改变的是局部变量的存储区域），只有整个程序结束，生命周期才结束
//	a++;			 //所以此时的a出大括号生命周期没有结束，而是进入下一次循环
//	printf("%d\n", a);
//}//一般情况下，a每次出大括号表示生命周期结束；再次进入下一次循环时，重新创建变量
//int main()
//{
//	int i = 0;
//	for (i = 0; i < 5; i++)//表示循环5次
//	{
//		test();
//	}
//
//	return 0;
//}



//<14>static修饰全局变量
// int a = 0;//全局变量，放在外部源文件中
//extern int a;//声明外部源文件，而非头文件
//			 //放在外部源文件中的全局变量可以声明使用，说明全局变量具有外部链接属性
//			 //但是，全局变量是有风险的，因为放在外部源文件中，大家都可以使用和改变，或者放在本源文件中，自己写的全局变量会被他人引用或改变
//void test()
//{
//	printf("2:	%d\n", a);
//}
//int main()
//{
//	printf("1:	%d\n", a);
//	test();
//	printf("3:	%d\n", a);
//
//	return 0;
//}


//static int a = 0;//在外部源文件中，或本源文件中，加上static修饰全局变量，全局变量就不再具有外部链接属性，而是变成内部链接属性
				   //因此全局变量不会被他人引用和改变，变得相对安全
//extern int a;//声明外部源文件，而非头文件
//				//放在外部源文件中的全局变量可以声明使用，说明全局变量具有外部链接属性
//				//但是，全局变量是有风险的，因为放在外部源文件中，大家都可以使用和改变，或者放在本源文件中，自己写的全局变量会被他人引用或改变
//void test()
//{
//	printf("2:	%d\n", a);
//}
//int main()
//{
//	printf("1:	%d\n", a);
//	test();
//	printf("3:	%d\n", a);
//
//	return 0;
//}


//外部源文件的函数
//int Add(int a, int b)
//{
//	return a + b;
//}

//extern int Add(int a, int b);//函数也可以放在外部源文件中，供大家使用和改变，说明函数也是具有外部链接属性的，或在本源文件中，供他人使用和改变
//							 //但是容易被改变，也是具有风险的，所以加上static修饰函数，外部链接属性会变成内部链接属性，从而只能在本源文件中使用
//							 //注：外部源文件的函数可以不加extern声明，甚至可以不用声明
//int main()
//{
//	int a = 0;
//	int b = 0;
//	scanf("%d %d", &a, &b);
//	int c = Add(a,b);
//	printf("%d\n", c);
//	return 0;
//}
